package com.yvdelx.cyclowomen.connector;

import android.os.Environment;

import com.yvdelx.cyclowomen.object.Profile;
import com.yvdelx.cyclowomen.utility.LogUtility;
import com.yvdelx.cyclowomen.utility.StringUtility;

import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.simpleframework.xml.transform.RegistryMatcher;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

/**
 * Manage the XML backup file
 * Created by ydelvaux on 23/02/14.
 */
public class XmlWriter {

    private static Class xmlWriterClass = XmlWriter.class;

    private static File parameterFile;

    private static Boolean isFileExist = false;

    private static String pathDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() +
            StringUtility.CST_XML_PATH_DIRECTORY;

    private static String pathFile = Environment.getExternalStorageDirectory().getAbsolutePath() +
            StringUtility.CST_XML_PATH_COMPLETE;

    /**
     * Verify if the backup file exist
     *
     * @return Boolean
     * @throws IOException
     */
    public static Boolean isFileExist() throws IOException {
        // If the parameter file is nullable it's the first call and the app need to charge the file
        if (parameterFile == null) {
            LogUtility.debug(xmlWriterClass, "The backup file is nullable in the app");
            getFile();
        }
        return isFileExist;
    }

    /**
     * Save data in the backup file
     *
     * @param profile Profile
     * @throws Exception
     */
    public static void saveData(Profile profile) throws Exception {
        LogUtility.debug(xmlWriterClass, "Backup in progress...");
        LogUtility.debug(xmlWriterClass, "File path : " + parameterFile.getAbsolutePath());
        RegistryMatcher matcher = new RegistryMatcher();
        matcher.bind(Date.class, new CustomDateFormatTransformer());
        Serializer serializer = new Persister(matcher);
        serializer.write(profile, parameterFile);
        LogUtility.debug(xmlWriterClass, "Backup finished !");
    }

    /**
     * Get the backup file
     *
     * @return File
     */
    public static File getFile() {
        parameterFile = new File(pathFile);
        isFileExist = parameterFile.exists();
        LogUtility.debug(XmlWriter.class, "File exists ? --> " + isFileExist);
        // If the file doesn't exist, the app create it.
        if (!isFileExist) {
            LogUtility.debug(XmlWriter.class, "Backup file is creating...");
            parameterFile = createExternalStoragePrivateFile();
            LogUtility.debug(XmlWriter.class, "Backup file created");
        }

        return parameterFile;
    }

    /**
     * Create the file on the storage if it doesn't exist
     *
     * @return File
     */
    public static File createExternalStoragePrivateFile() {
        File file = null;
        LogUtility.debug(xmlWriterClass, "Path directory : " + pathDirectory);
        try {
            File mFolder = new File(pathDirectory);
            // If the folder doesn't exist on the phone, the app create it.
            if (!mFolder.exists()) {
                //noinspection ResultOfMethodCallIgnored
                mFolder.mkdirs();
                LogUtility.debug(XmlWriter.class, "Folder created");
            }

            file = new File(pathDirectory, StringUtility.CST_XML_PATH_FILENAME);
            pathFile = file.getAbsolutePath();

            String nullable = ""; // At the creation of the file, the app don't put any datas.
            InputStream is = new ByteArrayInputStream(nullable.getBytes("UTF-8"));
            FileOutputStream fos = new FileOutputStream(file);
            byte[] data = new byte[is.available()];
            //noinspection ResultOfMethodCallIgnored
            is.read(data);
            fos.write(data);
            fos.flush();
            fos.close();

        } catch (IOException e) {
            LogUtility.error(xmlWriterClass, "ExternalStorage - Error writing : " + pathFile, e);
        }
        return file;
    }

    /**
     * Read the XML backup and return the associated profile
     *
     * @return Profile profile
     * @throws Exception
     */
    public static Profile getData() throws Exception {
        try {
            Serializer serializer = new Persister();
            File file = getFile();
            // The boolean at true signify the XML is read with the strict method.
            Profile profile = serializer.read(Profile.class, file, false);

            if (profile != null) {
                LogUtility.debug(xmlWriterClass, "Profile founded !");
            } else {
                LogUtility.debug(xmlWriterClass, "Profile not found.");
            }

            return profile;
        } catch (Exception e) {
            LogUtility.error(xmlWriterClass, e.getMessage(), e);
            throw e;
        }

    }
}
